home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-02-01 | 15.0 KB | 568 lines | [TEXT/KAHL] |
- /* main.c */
-
- /* plays sound/noisetracker files on Sparc, silicon graphics.
- * Authors : Liam Corner - zenith@dcs.warwick.ac.uk
- * Marc Espie - espie@ens.fr
- * Steve Haehnichen - shaehnic@ucsd.edu
- * Andrew Leahy - alf@st.nepean.uws.edu.au
- *
- * Usage : tracker <filename>
- * this version plays compressed files as well.
- */
-
- /* $Id: main.c,v 4.2 1994/01/13 09:16:00 espie Exp espie $
- * $Log: main.c,v $
- * Revision 4.2 1994/01/13 09:16:00 espie
- * *** empty log message ***
- *
- * Revision 1.10 1994/01/12 16:12:34 espie
- * Last minute changes.
- *
- * Revision 4.1 1994/01/12 16:11:07 espie
- * Last minute changes.
- *
- * Revision 4.0 1994/01/11 17:49:27 espie
- * Base main.c for unix and others.
- *
- * Revision 1.11 1994/01/09 17:36:22 Espie
- * Generalized open.c.
- *
- * Revision 1.10 1994/01/09 04:50:56 Espie
- * ?
- *
- * Revision 1.9 1994/01/08 03:55:43 Espie
- * Slight input/output changes.
- * No more call to create_notes_table().
- *
- * Revision 1.8 1994/01/08 02:04:21 Espie
- * Some notice to status.
- *
- * Revision 1.7 1994/01/06 22:32:42 Espie
- * Use new pref scheme.
- *
- * Revision 1.6 1994/01/05 16:10:49 Espie
- * *** empty log message ***
- *
- * Revision 1.5 1994/01/05 14:54:09 Espie
- * *** empty log message ***
- *
- * Revision 1.4 1994/01/05 13:50:43 Espie
- * Cosmetic change.
- *
- * Revision 1.3 1993/12/28 13:54:44 Espie
- * Use info facility instead of printf for usage message.
- *
- * Revision 1.2 1993/12/26 18:54:21 Espie
- * Modified in a more consistent way.
- *
- * Revision 1.1 1993/12/26 00:55:53 Espie
- * Initial revision
- *
- * Revision 3.20 1993/12/04 17:15:18 espie
- * New version.
- *
- * Revision 3.19 1993/12/04 16:12:50 espie
- * Options changes.
- *
- * Revision 3.18 1993/12/02 15:45:33 espie
- * Changed extended file semantics.
- *
- * Revision 3.17 1993/11/17 15:31:16 espie
- * New version.
- *
- * Revision 3.16 1993/11/11 20:00:03 espie
- * Amiga support.
- *
- * Revision 3.15 1993/08/04 11:55:21 espie
- * Fixed upo previous song bug.
- *
- * Revision 3.13 1993/07/18 10:39:44 espie
- * Added forking under unix. Experimental...
- *
- * Revision 3.11 1993/05/09 14:06:03 espie
- * Fixed up bug with mix option no longer working.
- *
- * Revision 3.10 1993/04/25 15:13:36 espie
- * Force new version.
- *
- * Revision 3.9 1993/01/15 14:00:28 espie
- * Added bg/fg test.
- *
- * Revision 3.7 1992/12/03 15:00:50 espie
- * restore stty.
- *
- * Revision 3.5 1992/11/24 10:51:19 espie
- * Added loads of new options.
- *
- * Revision 3.3 1992/11/22 17:20:01 espie
- * Augmented usage.
- *
- * Revision 3.2 1992/11/20 14:53:32 espie
- * Added finetune.
- *
- * Revision 3.1 1992/11/19 20:44:47 espie
- * Protracker commands.
- *
- * Revision 3.0 1992/11/18 16:08:05 espie
- * New release.
- *
- * Revision 2.20 1992/11/17 17:06:25 espie
- * Added PREVIOUS_SONG handling ???
- * Use streamio for new interface (obsolescent signal handlers), and
- * related changes.
- * Cleaned up path reader, and better signal handling.
- * Support for open_file.
- * Added imask.
- * Use transparent decompression/path lookup through open_file/close_file.
- * Added setup_audio().
- * Added some frequency/oversample/stereo change on the fly.
- * Necessitates rightful closing/reopening of audio.
- * Added compression methods. Changed getopt.
- * Separated mix/stereo stuff.
- * Added transpose feature.
- * Added possibility to get back to MONO for the sgi.
- * Added stereo capabilities to the indigo version.
- * Added recovery and reread for automatic recognition
- * of old/new tracker files.
- * Added two level of fault tolerancy.
- * Added more rational options.
- * Moved almost everything to audio and automaton.
- * Structured part of the code, especially replay ``automaton''
- * and setting up of effects.
- *
- * Revision 1.26 1991/11/17 17:09:53 espie
- * Added missing prototypes.
- * Some more info while loading files.
- * Added FAULT env variable, FAULT resistant playing,
- * for playing modules which are not quite correct.
- * Serious bug: dochangespeed was not reset all the time.
- * Check all these parameters, they MUST be reset for
- * each new song.
- * Fixed a stupid bug: when env variable LOOPING was
- * undefined, we got a segv on strcmp.
- * Now we just test for its existence, since this is
- * about all we want...
- * Bug correction: when doing arpeggio, there might not
- * be a new note, so we have to save the old note value
- * and do the arppeggio on that note.
- * Completely added control with OVERSAMPLE and FREQUENCY.
- * Added control flow.
- * Added pipe decompression, so that now you can do
- * str32 file.Z directly.
- * stdin may go away.
- * Added arpeggio.
- * Added vibslide and portaslide.
- * Added speed command.
- * Added signal control.
- * Error checking: there shouldn't be that many
- * segv signals any more.
- * Moved every command to commands.c.
- * Added some debug code for showing the full
- * sequence for a file.
- * Corrected the bug in volume slide: there is
- * no default value, i.e., if it is 0, it is 0,
- * as stupid as it may seem.
- * Added vibrato.
- * Added fastskip/corrected skip.
- * Modified control flow of the player till
- * it looks like something reasonable (i.e.,
- * the structure is more natural and reflects
- * the way stuff is played actually...)
- * Do not restart the sound when we change instruments
- * on the fly. A bit strange, but it works that way.
- * Modified main to use new data structures.
- * The sound player is MUCH cleaner, it uses now
- * a 3-state automaton for each voice.
- * Corrected ruckus with data type of sample.
- */
-
-
- #include "defs.h"
-
- #include <stdio.h>
- #include <signal.h>
- #include <stdlib.h>
- #include <string.h>
- #ifdef MALLOC_NOT_IN_STDLIB
- #include <malloc.h>
- #endif
- #include <ctype.h>
- #ifdef VOLUME_CONTROL
- #ifdef __hpux
- #define true /* kludge to avoid typedef of boolean (name clash with macro) */
- #include <audio/Alib.h>
- #undef true
- AGainDB volume = -20;
- char use_speaker = 0;
- #endif
- #endif
-
-
- #include "song.h"
- #include "extern.h"
- #include "options.h"
-
- #include "getopt.h"
- #include "tags.h"
- #include "prefs.h"
-
- ID("$Id: main.c,v 4.2 1994/01/13 09:16:00 espie Exp espie $")
-
-
- LOCAL void print_usage()
- {
- GENERIC handle;
-
- handle = begin_info("Usage");
- info(handle, "Usage: tracker [options] filename [...]");
- info(handle, "-help Display usage information");
- info(handle, "-quiet Print no output other than errors");
- info(handle, "-picky Do not tolerate any faults (default is to ignore most)");
- info(handle, "-tolerant Ignore all faults");
- info(handle, "-mono Select single audio channel output");
- info(handle, "-stereo Select dual audio channel output");
- info(handle, "-verbose Show text representation of song");
- info(handle, "-repeats <count> Number of repeats (0 is forever) (default 1)");
- info(handle, "-speed <speed> Song speed. Some songs want 60 (default 50)");
- info(handle, "-mix <percent> Percent of channel mixing. (0 = spatial, 100 = mono)");
- info(handle, "-new -old -both Select default reading type (default is -both)");
- info(handle, "-frequency <freq> Set playback frequency in Hz");
- info(handle, "-oversample <times> Set oversampling factor");
- info(handle, "-transpose <n> Transpose all notes up");
- info(handle, "-scroll Show what's going on");
- info(handle, "-sync Try to synch audio output with display");
- #ifdef VOLUME_CONTROL
- info(handle, "-speaker Output audio to internal speaker");
- info(handle, "-volume <n> Set volume in dB");
- #endif
- info(handle, "");
- info(handle, "RunTime:");
- info(handle, "e,x exit program");
- info(handle, "n next song");
- info(handle, "p restart/previous song");
- info(handle, "> fast forward");
- info(handle, "< rewind");
- info(handle, "S NTSC tempo\t s\tPAL tempo");
- end_info(handle);
- }
-
- /* Command-line options. */
- LOCAL struct long_option long_options[] =
- {
- {"help", 0, 'H', OPT_HELP},
- {"quiet", 0, 'Q', OPT_QUIET},
- {"picky", 0, 'P', OPT_PICKY},
- {"tolerant", 0, 'L', OPT_TOLERANT},
- {"new", 0, 'N', OPT_NEWONLY},
- {"old", 0, 'O', OPT_OLDONLY},
- {"both", 0, 'B', OPT_BOTH},
- {"mono", 0, 'M', OPT_MONO},
- {"stereo", 0, 'S', OPT_STEREO},
- {"verbose", 0, 'V', OPT_VERBOSE},
- {"frequency", 1, 'f', OPT_FREQUENCY},
- {"oversample", 1, 'o', OPT_OVERSAMPLE},
- {"transpose", 1, 't', OPT_TRANSPOSE},
- {"repeats", 1, 'r', OPT_REPEATS},
- {"speed", 1, 's', OPT_SPEED},
- {"mix", 1, 'm', OPT_MIX},
- {"start", 1, 'X', OPT_START},
- {"cut", 1, '-', OPT_CUT},
- {"add", 1, '+', OPT_ADD},
- {"scroll", 0, 'v', OPT_SHOW},
- {"sync", 0, '=', OPT_SYNC},
- #ifdef VOLUME_CONTROL
- {"speaker", 0, '#', OPT_SPEAKER},
- {"volume", 1, 'u', OPT_VOLUME},
- #endif
- {0, 0, 0 , 0}
- };
-
-
- /* global variable to catch various types of errors
- * and achieve the desired flow of control
- */
- int error;
-
- LOCAL int optvalue(def)
- int def;
- {
- int d;
-
- if (sscanf(optarg, "%d", &d) == 1)
- return d;
- else
- {
- optind--;
- return def;
- }
- }
-
- LOCAL struct song *do_read_song(name, type)
- char *name;
- int type;
- {
- struct song *song;
- struct exfile *file;
-
- file = open_file(name, "r", getenv("MODPATH"));
- if (!file)
- return NULL;
- song = read_song(file, type);
- close_file(file);
- return song;
- }
-
- LOCAL int ask_freq;
- LOCAL int oversample;
- LOCAL int stereo;
- LOCAL int start;
- LOCAL int transpose;
-
-
- LOCAL void parse_options(argc, argv)
- int argc;
- char *argv[];
- {
- int c;
-
- while ((c = getlongopt(argc, argv, long_options))
- != BAD_OPTION)
- switch(c)
- {
- case OPT_CUT:
- case OPT_ADD:
- {
- int i;
- unsigned long imask = 0;
-
- for (i = 0; optarg[i]; i++)
- {
- char c = tolower(optarg[i]);
-
- if (c >= '1' && c <= '9')
- imask |= 1<< (c-'1');
- else if (c >= 'a' && c <= 'z')
- imask |= 1 << (c-'a'+9);
- }
- if (c == OPT_ADD)
- set_pref_scalar(PREF_IMASK, imask);
- else
- set_pref_scalar(PREF_IMASK, ~imask);
- }
- break;
- case OPT_OLDONLY: /* old tracker type */
- set_pref_scalar(PREF_TYPE, OLD);
- break;
- case OPT_NEWONLY: /* new tracker type */
- set_pref_scalar(PREF_TYPE, NEW);
- break;
- case OPT_SHOW:
- set_pref_scalar(PREF_SHOW, TRUE);
- break;
- case OPT_SYNC:
- set_pref_scalar(PREF_SYNC, TRUE);
- break;
- case OPT_BOTH: /* both tracker types */
- set_pref_scalar(PREF_TYPE, BOTH);
- break;
- case OPT_REPEATS: /* number of repeats */
- set_pref_scalar(PREF_REPEATS, optvalue(0));
- break;
- case OPT_SPEED:
- set_pref_scalar(PREF_SPEED, optvalue(50));
- break;
- case OPT_MONO:
- stereo = FALSE;
- break;
- case OPT_STEREO:
- stereo = TRUE;
- break;
- case OPT_OVERSAMPLE:
- oversample = optvalue(1);
- break;
- case OPT_FREQUENCY:
- ask_freq = optvalue(0);
- break;
- case OPT_TRANSPOSE:
- transpose = optvalue(0);
- break;
- case OPT_PICKY:
- set_pref_scalar(PREF_TOLERATE, 0);
- break;
- case OPT_TOLERANT:
- set_pref_scalar(PREF_TOLERATE, 0);
- break;
- case OPT_MIX: /* % of channel mix.
- * 0->full stereo, 100->mono */
- set_mix(optvalue(30));
- break;
- case OPT_START:
- start = optvalue(0);
- break;
- case OPT_HELP:
- print_usage();
- end_all(0);
- /* NOTREACHED */
- case OPT_VERBOSE:
- set_pref_scalar(PREF_DUMP, TRUE);
- break;
- #ifdef VOLUME_CONTROL
- case OPT_VOLUME:
- volume = optvalue(-20);
- break;
- case OPT_SPEAKER:
- use_speaker = 1;
- break;
- #endif
- }
- }
-
- LOCAL struct song *load_song(name)
- char *name;
- {
- struct song *song;
- char *buffer;
- int i, j;
-
- i = strlen(name);
-
- for (j = i; j > 0; j--)
- if (name[j] == '/' || name[j] == '\\')
- {
- j++;
- break;
- }
-
- buffer = malloc( i - j + 5);
- if (buffer)
- {
- sprintf(buffer, "%s...", name + j);
- status(buffer);
- }
-
-
- switch(get_pref_scalar(PREF_TYPE))
- {
- case BOTH:
- song = do_read_song(name, NEW);
- if (song)
- break;
- /* FALLTHRU */
- case OLD:
- song = do_read_song(name, OLD);
- break;
- /* this is explicitly flagged as a new module,
- * so we don't need to look for a signature.
- */
- case NEW:
- song = do_read_song(name, NEW_NO_CHECK);
- break;
- }
- status(0);
- return song;
- }
-
- int main(argc, argv)
- int argc;
- char **argv;
- {
- struct song *song;
- boolean *is_song;
- int i;
-
- struct tag *result;
-
- is_song = (boolean *)malloc(sizeof(boolean) * argc);
- if (!is_song)
- end_all("No memory left");
-
- for (i = 0; i < argc; i++)
- is_song[i] = FALSE; /* For termination */
-
- start = 0;
- set_pref_scalar(PREF_IMASK, 0);
- set_pref_scalar(PREF_BCDVOL, 0);
- set_pref_scalar(PREF_DUMP, FALSE);
- set_pref_scalar(PREF_SHOW, FALSE);
- set_pref_scalar(PREF_SYNC, FALSE);
- set_pref_scalar(PREF_TYPE, BOTH);
- set_pref_scalar(PREF_REPEATS, 1);
- set_pref_scalar(PREF_SPEED, 50);
- set_pref_scalar(PREF_TOLERATE, 1);
-
- if (argc == 1)
- {
- print_usage();
- end_all(0);
- }
-
- ask_freq = read_env("FREQUENCY", 0);
- oversample = read_env("OVERSAMPLE", 1);
- transpose = read_env("TRANSPOSE", 0);
- stereo = !getenv("MONO");
- set_mix(30);
-
-
-
- /* check the command name for default reading type */
-
-
- optind = 1;
- for (optind = 1; optind < argc; optind++)
- {
- parse_options(argc, argv);
- if (optind >= argc)
- end_all(0);
-
-
- song = load_song(argv[optind]);
- if (song)
- is_song[optind] = TRUE;
- else
- {
- puts("not a song");
- is_song[optind] = FALSE;
- continue;
- }
- play_on:
- if (get_pref_scalar(PREF_DUMP))
- dump_song(song);
- transpose_song(song, transpose);
- setup_audio(ask_freq, stereo, oversample);
- result = play_song(song, start);
- release_song(song);
- status(0);
- while (result = get_tag(result))
- {
- switch (result->type)
- {
- case PLAY_PREVIOUS_SONG:
- optind--;
- while ((optind > 0) && !is_song[optind])
- optind--;
- if (optind == 0)
- end_all(0);
- else
- {
- song = load_song(argv[optind]);
- goto play_on;
- }
- /* NOTREACHED */
- case PLAY_LOAD_SONG:
- song = load_song(result->data.pointer);
- free(result->data.pointer);
- if (song)
- goto play_on;
- default:
- break;
- }
- result++;
- }
-
- }
- end_all(0);
- /* NOTREACHED */
- }
-
-
-